/* 
 *  Incub - incubate your baby robot
 *  Copyright (C) 2008 Stanislaw Szymczyk
 *  e-mail: sszymczy@gmail.com   www: http://cogville.cog-lab.com
 *
 *  This file is part of Incub.
 *
 *  Incub is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Incub is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Incub.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

#include <iostream>

#include "CorbaHelper.h"

void CorbaHelper::registerFactories(CORBA::ORB *orb) {
	CORBA::ValueFactoryBase_var factory;

	factory = new VTactileSensorOutFactory();
	orb->register_value_factory("IDL:VTactileSensorOut:1.0", factory);

	factory = new VWorldOutFactory();
	orb->register_value_factory("IDL:VWorldOut:1.0", factory);

	factory = new VWorldInFactory();
	orb->register_value_factory("IDL:VWorldIn:1.0", factory);

	factory = new VShapeOutFactory();
	orb->register_value_factory("IDL:VShapeOut:1.0", factory);

	factory = new VSensorOutFactory();
	orb->register_value_factory("IDL:VSensorOut:1.0", factory);

	factory = new VTactileMatrixOutFactory();
	orb->register_value_factory("IDL:VTactileMatrixOut:1.0", factory);

	factory = new VAngularVelocimeterOutFactory();
	orb->register_value_factory("IDL:VAngularVelocimeterOut:1.0", factory);

	factory = new VLinearVelocimeterOutFactory();
	orb->register_value_factory("IDL:VLinearVelocimeterOut:1.0", factory);

	factory = new VPositionSensorOutFactory();
	orb->register_value_factory("IDL:VPositionSensorOut:1.0", factory);

	factory = new VEntityOutFactory();
	orb->register_value_factory("IDL:VEntityOut:1.0", factory);

	factory = new VEntityInFactory();
	orb->register_value_factory("IDL:VEntityIn:1.0", factory);

	factory = new VCameraOutFactory();
	orb->register_value_factory("IDL:VCameraOut:1.0", factory);

	factory = new VJointOutFactory();
	orb->register_value_factory("IDL:VJointOut:1.0", factory);

	factory = new VJointInFactory();
	orb->register_value_factory("IDL:VJointIn:1.0", factory);

	factory = new VMotorOutFactory();
	orb->register_value_factory("IDL:VMotorOut:1.0", factory);

	factory = new VMotorInFactory();
	orb->register_value_factory("IDL:VMotorIn:1.0", factory);

	factory = new VVelocityControlledMotorOutFactory();
	orb->register_value_factory("IDL:VVelocityControlledMotorOut:1.0", factory);

	factory = new VVelocityControlledMotorInFactory();
	orb->register_value_factory("IDL:VVelocityControlledMotorIn:1.0", factory);

	factory = new VTorqueControlledMotorOutFactory();
	orb->register_value_factory("IDL:VTorqueControlledMotorOut:1.0", factory);

	factory = new VTorqueControlledMotorInFactory();
	orb->register_value_factory("IDL:VTorqueControlledMotorIn:1.0", factory);
}

CORBA::Object_ptr CorbaHelper::getGateReference(CORBA::ORB_ptr orb) {
	CosNaming::NamingContext_var rootContext;
  
	try {
		// Obtain a reference to the root context of the Name service:
		CORBA::Object_var obj;
		obj = orb->resolve_initial_references("NameService");

		// Narrow the reference returned.
		rootContext = CosNaming::NamingContext::_narrow(obj);
		if( CORBA::is_nil(rootContext) ) {
			std::cerr << "Failed to narrow the root naming context." << std::endl;
			return CORBA::Object::_nil();
		}
	} catch(CORBA::ORB::InvalidName& ex) {
		// This should not happen!
		std::cerr << "Service required is invalid [does not exist]." << std::endl;
		return CORBA::Object::_nil();
	}

	// Create a name object, containing the name test/context:
	CosNaming::Name name;
	name.length(2);
	
	name[0].id   = (const char*) "enaction";       // string copied
	name[0].kind = (const char*) "my_context"; // string copied
	name[1].id   = (const char*) "Gate";
	name[1].kind = (const char*) "Object";

	try {
		// Resolve the name to an object reference.
		return rootContext->resolve(name);
	} catch(CosNaming::NamingContext::NotFound& ex) {
		// This exception is thrown if any of the components of the
		// path [contexts or the object] aren't found:
		std::cerr << "Context not found." << std::endl;
		exit(1);
	} catch(CORBA::COMM_FAILURE& ex) {
		std::cerr << "Caught system exception COMM_FAILURE -- unable to contact the "
			<< "naming service." << std::endl;
		exit(1);
	} catch(CORBA::SystemException&) {
		std::cerr << "Caught a CORBA::SystemException while using the naming service."
			<< std::endl;
		exit(1);
	}

	return CORBA::Object::_nil();
}
